#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;

namespace zch{
    class String{
    public:
        typedef char* iterator;
    public:
        iterator begin()
        {
            return _str;
        }

        iterator end()
        {
            return _str + _size;
        }
    public:
        String(const char* str = "")
        :_str(nullptr)
        ,_capacity(0)
        ,_size(0)
        {
            cout << "默认构造" << endl;
            _size = _capacity = strlen(str);
            _str = new char[_capacity + 1];
            if(_str == nullptr)
            {
                exit(1);
            }
            strcpy(_str, str);
        }

        String(const String& str)
        :_str(nullptr)
        ,_size(0)
        ,_capacity(0)
        {
            cout << "拷贝构造" << endl;
            _str = new char[str._capacity + 1];
            _size = str._size;
            _capacity = str._capacity;

            strcpy(_str, str._str);
        }
        
        String(String&& s)
        :_str(nullptr)
        ,_size(0)
        ,_capacity(0)
        {
            cout << "移动构造" << endl;
            Swap(s);
        }

        String& operator=(const String& str)
        {
            cout << "拷贝赋值" << endl;
            if(this != &str) //防止自己拷贝自己
            {
                String tmp(str);
                swap(_str, tmp._str);
                _size = tmp._size;
                _capacity = tmp._capacity;
                
                return *this;
            }
        }

        String& operator=(String&& str)
        {
            cout << "移动赋值" << endl;
            Swap(str);
            return *this;
        }

        size_t size()
        {
            return _size;
        }

        size_t capacity()
        {
            return _capacity;
        }

        void resize(size_t n, const char c = '\0')
        {
            if(n > _capacity)
            {
                reserve(n);
                for(int i = _size; i < _capacity; i++)
                {
                    _str[i] = c;
                }

                _str[n] = '\0';
                _size = n;
            }
            else
            {
                _str[n] = '\0';
                _size = n;
            }
        }

        const char* c_str()
        {
            return _str;
        }

        void reserve(size_t n)
        {
            if(n > _capacity)
            {
                // 扩容
                char *tmp = new char[n + 1];
                strcpy(tmp, _str);
                swap(tmp, _str);
                delete[] tmp;
                _capacity = n;
            }
        }

        void push_back(const char c)
        {
            if(_size == _capacity)
            {
                size_t newCapacity = _capacity == 0? 4 : _capacity * 2;
                reserve(newCapacity);
                _capacity = newCapacity;
            }

            _str[_size] = c;
            ++_size;
            _str[_size] = '\0';
        }

        ~String()
        {
            if(_str != nullptr)
                delete[] _str;
                _size = _capacity = 0;
                _str = nullptr;
        }
    private:
        void Swap(String& s1)
        {
            ::swap(_str, s1._str);
            ::swap(_size, s1._size);
            ::swap(_capacity, s1._capacity);
        }
    private:
        char *_str;
        size_t _capacity;
        size_t _size;
    };
    
    String to_String(int value)
    {
        bool flag = true;
        if(value < 0)
        {
            flag = false;
            value = -value;
        }

        String s;
        while(value > 0)
        {
            int n = value % 10;
            s.push_back(n + '0');
            value /= 10;
        }

        if(flag == false)
        {
            s.push_back('-');
        }

        reverse(s.begin(), s.end());
        //cout << s._str << endl;
        return s;
    }
    

    // void test1()
    // {
    //     char p[] = "abcdefg";
    //     zch::String str(p);
    //     cout << str._str << endl;
    // }

    // void test2()
    // {
    //     char p[] = "abcdefg";
    //     zch::String str1(p);
    //     zch::String str2(str1);
    //     cout << str1._str << endl;
    //     cout << str2._str << endl;
    // }

    // void test3()
    // {
    //     char p[] = "abcdefg";
    //     zch::String str1(p);
    //     zch::String str2(str1);
    //     zch::String str3 = str2;
    //     cout << str1._str << endl;
    //     cout << str2._str << endl;
    //     cout << str3._str << endl;

    //     for(auto e : str3)
    //     {
    //         cout << e;
    //     }
    //     cout << endl;
    // }

    // void test4()
    // {
    //     zch::String str1("abcdefgh");
    //     zch::String str2("abcdefgh");

    //     cout << str1.size() << endl;
    //     cout << str2.size() << endl;
    //     cout << str1._str << endl;
    //     cout << str2._str << endl;
    //     cout << str1.capacity() << endl;
    //     cout << str2.capacity() << endl;

    //     str1.resize(15, 'a');
    //     str2.reserve(30);

    //     cout << str1.size() << endl;
    //     cout << str2.size() << endl;
    //     cout << str1._str << endl;
    //     cout << str2._str << endl;
    //     cout << str1.capacity() << endl;
    //     cout << str2.capacity() << endl;
    // }

    void test5()
    {
        String str1("abcdefg");
        char s[] = "abcdefg";
        String str2(s);

        String str3(str1);
        String str4(to_String(1234));
        cout << typeid(to_String(1234)).name() << endl;
        cout << typeid(str1).name() << endl;
        // cout << "str4: " << to_String(1234)._str << endl;
    }
}